﻿// OneScript: ./OInt/core/Modules/OPI_GoogleSheets.os
// Lib: Google Sheets
// CLI: gsheets

// MIT License

// Copyright (c) 2023 Anton Tsitavets

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// https://github.com/Bayselonarrend/OpenIntegrations

// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off

//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content

// Раскомментировать, если выполняется OneScript
#Использовать "../../tools"

#Область ПрограммныйИнтерфейс

#Область РаботаСКнигами

// Создать книгу
// Создает новую книгу
// 
// Параметры:
//  Токен            - Строка           - Токен                                           - token
//  Наименование     - Строка           - Наименование                                    - title
//  МассивИменЛистов - Массив из Строка - Массив имен для добавления новых листов в книгу - sheets
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция СоздатьКнигу(Знач Токен, Знач Наименование, Знач МассивИменЛистов) Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
    OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивИменЛистов);
    
    Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL       = "https://sheets.googleapis.com/v4/spreadsheets";
   
    Свойства  = Новый Структура("title" , Наименование);
    Листы     = Новый Массив;
    
    ЗаполнитьМассивЛистов(МассивИменЛистов, Листы);
    
    Параметры = Новый Структура;
    OPI_Инструменты.ДобавитьПоле("properties", Свойства, "Коллекция", Параметры);
    OPI_Инструменты.ДобавитьПоле("sheets"    , Листы   , "Коллекция", Параметры);
    
    Ответ = OPI_Инструменты.Post(URL, Параметры, Заголовки);
    
    Возврат Ответ;

КонецФункции

// Получить книгу
// Получает информацию о книге по ID
// 
// Параметры:
//  Токен         - Строка - Токен               - token
//  Идентификатор - Строка - Идентификатор книги - spreadsheet
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьКнигу(Знач Токен, Знач Идентификатор) Экспорт

    OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор); 
    
    Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL       = "https://sheets.googleapis.com/v4/spreadsheets/" + Идентификатор;
    
    Ответ = OPI_Инструменты.Get(URL, , Заголовки);
    
    Возврат Ответ;

КонецФункции

// Изменить наименование книги
// Изменяет наименование существующей книги
// 
// Параметры:
//  Токен        - Строка - Токен              - token
//  Книга        - Строка - ID книги           - spreadsheet
//  Наименование - Строка - Новое наименование - title
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ИзменитьНаименованиеКниги(Знач Токен, Знач Книга, Знач Наименование) Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
    
    Заголовки    = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL          = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + ":batchUpdate";
    
    Изменение       = Новый Структура("title", Наименование);
    ЗапросИзменения = Новый Структура("properties,fields", Изменение, "title");
    Запрос          = Новый Структура("updateSpreadsheetProperties", ЗапросИзменения);
    
    МассивЗапросов  = Новый Массив;
    МассивЗапросов.Добавить(Запрос);
    
    Параметры = Новый Структура("requests", МассивЗапросов);
        
    Ответ     = OPI_Инструменты.Post(URL, Параметры, Заголовки);
    
    Возврат Ответ;
    
КонецФункции

#КонецОбласти

#Область РаботаСЛистами

// Добавить лист
// Добавляет новый лист в книгу
// 
// 
// Параметры:
//  Токен        - Строка - Токен                     - token
//  Книга        - Строка - Идентификатор книги       - spreadsheet
//  Наименование - Строка - Наименование нового листа - title
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ДобавитьЛист(Знач Токен, Знач Книга, Знач Наименование) Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
        
    Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL       = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + ":batchUpdate";
    Лист      = СоздатьЛист(Наименование);
    
    Запросы   = Новый Массив;
    Изменение = Новый Структура("addSheet", Лист);
    Запросы.Добавить(Изменение);
    
    Параметры = Новый Структура("requests", Запросы);
    
    Ответ = OPI_Инструменты.Post(URL, Параметры, Заголовки);
    
    Возврат Ответ;

КонецФункции

// Удалить лист
// Удаляет лист из книги
// 
// Параметры:
//  Токен   - Строка - Токен                          - token
//  Книга   - Строка - Идентификатор книги            - spreadsheet
//  Лист    - Строка - Идентификатор удаляемого листа - sheet
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УдалитьЛист(Знач Токен, Знач Книга, Знач Лист) Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист);
        
    Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL       = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + ":batchUpdate";
    
    Запросы   = Новый Массив;
    Лист      = Новый Структура("sheetId"    , Лист);
    Изменение = Новый Структура("deleteSheet", Лист);
    Запросы.Добавить(Изменение);
    
    Параметры = Новый Структура("requests", Запросы);
    
    Ответ = OPI_Инструменты.Post(URL, Параметры, Заголовки);
    
    Возврат Ответ;

КонецФункции

// Копировать лист
// Копирует лист из одной книги в другую
// 
// Параметры:
//  Токен  - Строка - Токен - token
//  Откуда - Строка - ID книги источника   - from
//  Куда   - Строка - ID книги приемника   - to
//  Лист   - Строка - ID копируемого листа - sheet
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция КопироватьЛист(Знач Токен, Знач Откуда, Знач Куда, Знач Лист) Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Откуда);
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Куда);
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист);
        
    Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL       = "https://sheets.googleapis.com/v4/spreadsheets/"
        + Откуда
        + "/sheets/"
        + Лист
        + ":copyTo";
    
    Параметры = Новый Структура("destinationSpreadsheetId", Куда);  
    Ответ     = OPI_Инструменты.Post(URL, Параметры, Заголовки);
    
    Возврат Ответ;
   
КонецФункции

#КонецОбласти

#Область РаботаСДанными

// Установить значения ячеек
// Устанавливает значения ячеек листа
// 
// Параметры:
//  Токен                - Строка                        - Токен    - token
//  Книга                - Строка                        - ID книги - spreadsheet 
//  СоответствиеЗначений - Соответствие Из КлючИЗначение - Данные заполнения, где ключ это имя ячейки вида A1   - data
//  Лист                 - Строка                        - Имя листа (первый лист по умолчанию) - sheetname
//  ОсновноеИзмерение    - Строка                        - Основное измерение при заполнении диапазона массивом - dim
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УстановитьЗначенияЯчеек(Знач Токен
    , Знач Книга
    , Знач СоответствиеЗначений
    , Знач Лист = ""
    , Знач ОсновноеИзмерение = "COLUMNS") Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
    OPI_ПреобразованиеТипов.ПолучитьКоллекцию(СоответствиеЗначений);
    
    Если Не ТипЗнч(СоответствиеЗначений) = Тип("Структура")
        И Не ТипЗнч(СоответствиеЗначений) = Тип("Соответствие") Тогда
        Возврат "Не удалось привести структуру значений к коллекции";
    КонецЕсли;
    
    Заголовки    = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL          = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + "/values:batchUpdate";
    МассивДанных = СформироватьМассивДанныхЯчеек(СоответствиеЗначений, ОсновноеИзмерение, Лист);

    Параметры = Новый Структура("data,valueInputOption", МассивДанных, "USER_ENTERED");
    Ответ     = OPI_Инструменты.Post(URL, Параметры, Заголовки);
    
    Возврат Ответ;
    
КонецФункции

// Очистить ячейки
// Очищает значение в ячейках
// 
// Параметры:
//  Токен       - Строка           - Токен                                - token
//  Книга       - Строка           - ID книги                             - spreadsheet
//  МассивЯчеек - Массив из Строка - Массив ячеек вида А1 для очистки     - cells
//  Лист        - Строка           - Имя листа (первый лист по умолчанию) - sheetname
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ОчиститьЯчейки(Знач Токен, Знач Книга, Знач МассивЯчеек, Знач Лист = "") Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
    OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивЯчеек);
    
    Заголовки    = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL          = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + "/values:batchClear";
    
    СформироватьМассивИменЯчеек(МассивЯчеек, Лист);
        
    Параметры = Новый Структура("ranges", МассивЯчеек);
    Ответ     = OPI_Инструменты.Post(URL, Параметры, Заголовки);
    
    Возврат Ответ;
    
КонецФункции

// Получить значения ячеек
// Получает значения ячеек таблицы
// 
// Параметры:
//  Токен       - Строка           - Токен                                                              - token
//  Книга       - Строка           - ID книги                                                           - spreadsheet
//  МассивЯчеек - Массив из Строка - Массив ячеек вида А1 для получения (весь лист, если не заполнено)  - cells
//  Лист        - Строка           - Имя листа (первый лист по умолчанию)                               - sheetname
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьЗначенияЯчеек(Знач Токен, Знач Книга, Знач МассивЯчеек = "", Знач Лист = "") Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
      
    Заголовки    = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
    URL          = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + "/values:batchGet";
  
    Если ЗначениеЗаполнено(МассивЯчеек) Тогда
        OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивЯчеек);  
        СформироватьМассивИменЯчеек(МассивЯчеек, Лист);
        
        Первый = Истина;
        Для Каждого Ячейка Из МассивЯчеек Цикл
            Разделитель = ?(Первый, "?", "&");
            URL         = URL + Разделитель + "ranges=" + Ячейка;
            Первый      = Ложь;
        КонецЦикла;
    Иначе
        URL = URL + "?ranges='" + Лист + "'";
    КонецЕсли;
    
    Ответ = OPI_Инструменты.Get(URL, , Заголовки);
    
    Возврат Ответ;
    
КонецФункции

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Процедура ЗаполнитьМассивЛистов(Знач МассивИмен, МассивЛистов)
    
    Для Каждого ИмяЛиста Из МассивИмен Цикл
        
        Лист = СоздатьЛист(ИмяЛиста);
        МассивЛистов.Добавить(Лист);
        
    КонецЦикла;

КонецПроцедуры

Процедура ДобавитьИмяЛиста(Ячейка, Знач Лист)
    
    Если ЗначениеЗаполнено(Лист) Тогда
		Ячейка     = "'" + Лист + "'!" + Ячейка;
    КонецЕсли;
    
КонецПроцедуры

Функция СоздатьЛист(Знач Наименование)
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
    
    СвойстваЛиста = Новый Структура("title"     , Наименование);
    Лист          = Новый Структура("properties", СвойстваЛиста);

    Возврат Лист;
    
КонецФункции

Функция СформироватьМассивДанныхЯчеек(Знач СтруктураЗначений, Знач ОсновноеИзмерение, Знач Лист)
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист);
    
    МассивДанных = Новый Массив;
    
    Для Каждого ДанныеЯчейки Из СтруктураЗначений Цикл
        
        ТекущееЗначение = ДанныеЯчейки.Значение;
        ТекущийКлюч     = ДанныеЯчейки.Ключ;
        
        ДобавитьИмяЛиста(ТекущийКлюч, Лист);
        
        OPI_ПреобразованиеТипов.ПолучитьМассив(ТекущееЗначение);
        
        ТекущиеДанные   = Новый Соответствие;
        ТекущийМассив   = Новый Массив;
        
        ТекущийМассив.Добавить(ТекущееЗначение);
        
        OPI_Инструменты.ДобавитьПоле("range"         , ТекущийКлюч      , "Строка", ТекущиеДанные);
        OPI_Инструменты.ДобавитьПоле("values"        , ТекущийМассив    , "Массив", ТекущиеДанные);
        OPI_Инструменты.ДобавитьПоле("majorDimension", ОсновноеИзмерение, "Строка", ТекущиеДанные);
        
        МассивДанных.Добавить(ТекущиеДанные);
        
    КонецЦикла;
    
    Возврат МассивДанных;
    
КонецФункции

Процедура СформироватьМассивИменЯчеек(Знач МассивИмен, Знач Лист)

   OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист); 
   
   Для Н = 0 По МассивИмен.ВГраница() Цикл       
       ДобавитьИмяЛиста(МассивИмен[Н], Лист);
   КонецЦикла;
       
КонецПроцедуры

#КонецОбласти
